package org.ala.tiktools.mybatis.expand;

import org.ala.tiktools.mybatis.interceptor.IAnnotationInterceptor;
import org.apache.ibatis.binding.MapperProxy;
import org.apache.ibatis.binding.MapperProxyFactory;
import org.apache.ibatis.session.SqlSession;

import java.lang.reflect.Proxy;
import java.util.List;

/**
 * @author ala
 * @date 2025-01-07 13:47
 */
public class MapperProxyFactoryExpander<T> extends MapperProxyFactory<T> {


    /**
     * 被代理的接口
     */
    private final Class<T> mapperInterface;

    /**
     *  注解拦截器链
     *  <p> 执行顺序就是list顺序
     */
    protected List<IAnnotationInterceptor> annotationInterceptorChain;

    /**
     *  全局配置对象
     */
    protected ConfigurationExpander config;


    public MapperProxyFactoryExpander(Class<T> mapperInterface, ConfigurationExpander conf) {
        super(mapperInterface);
        this.mapperInterface = mapperInterface;
        this.config = conf;
    }


    @SuppressWarnings("unchecked")
    protected T newInstance(MapperProxy<T> mapperProxy) {
        return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface },
                mapperProxy);
    }


    /**
     * 真实创建的代理
     */
    public T newInstance(SqlSession sqlSession) {
        //	源码中创建的是MapperProxy，这里改成MapperProxyExpander
//		final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
        final MapperProxyExpander<T> mapperProxy = new MapperProxyExpander<T>(sqlSession, mapperInterface, getMethodCache(), config.getMapperMethodHolder());

        //  追加注解拦截器
        if (annotationInterceptorChain != null) {
            for (int i = 0 ; i < annotationInterceptorChain.size() ; i++) {
                mapperProxy.appendInterceptor(annotationInterceptorChain.get(i), i);
            }
        }

        return newInstance(mapperProxy);
    }


    public Class<T> getMapperInterface() {
        return mapperInterface;
    }

    public List<IAnnotationInterceptor> getAnnotationInterceptorChain() {
        return annotationInterceptorChain;
    }

    public void setAnnotationInterceptorChain(List<IAnnotationInterceptor> annotationInterceptorChain) {
        this.annotationInterceptorChain = annotationInterceptorChain;
    }
}
